<script setup lang="tsx">
import {h, ref, watch} from 'vue';
import {$t} from "@/locales";
import {NButton, NPopconfirm, NTag, SelectOption} from 'naive-ui'
import {useAppStore} from "@/store/modules/app";
import {useLoading} from "~/packages/hooks";
import {
  deleteDeployment,
  fetchGetDefinitionImage,
  fetchGetDeployPage,
  fetchMigrationDefinition,
  fetchUpdateDefinitionState
} from "@/service/api";
import ImgViewer from "@/components/common/img-viewer.vue";

defineOptions({
  name: 'FlowDeployDrawer'
});
const appStore = useAppStore();
const {loading, startLoading, endLoading} = useLoading();
const showMigrationModal = ref(false);
const fromProcessOptions = ref<SelectOption[]>([]);
const currentProcessDefinitionId = ref<string>('');
const fromProcessDefinitionId = ref<string>('');
const imgViewer = ref();
const emit = defineEmits<{
  (e: 'deploy-model', callback: Function): void;
}>();
const props = defineProps<{
  template: Api.Entity.Template
}>();
const showDrawer = ref(false);
const pagination = ref<Api.Common.Pageable>(
  {
    pageSize: 15,
    pageNumber: 1,
    searchProperty: null,
    searchValue: null,
    orderProperty: null,
    orderDirection: null,
    filters: null
  }
);
const data = ref<any[]>();
const columns = ref<any[]>([
  {
    key: 'id',
    title: '流程定义id',
    align: 'center',
  },
  {
    key: 'name',
    title: '名称',
    align: 'center',
    with: '50px',
  },
  {
    key: 'key',
    title: '标识',
    align: 'center',
    with: 80,
  },
  {
    key: 'version',
    title: '版本',
    align: 'center',
  },
  {
    key: 'suspensionState',
    title: '状态',
    align: 'center',
    render(row: Flow.ProcessDefinition) {
      let state = row.suspensionState === 1 ? '激活' : '挂起'
      return h(NTag, {
          style: {
            marginRight: '6px'
          },
          type: row.suspensionState === 1 ? 'success' : 'warning',
        },
        {
          default: () => state
        }
      )
    }
  },
  {
    key: 'resourceName',
    title: '流程xml',
    align: 'center',
  },
  {
    key: 'diagramResourceName',
    title: '流程图片',
    align: 'center',
    render(row: Flow.ProcessDefinition) {
      return h('a', {
        href: 'javascript:void(0);',
        style: {
          cursor: 'pointer',
          color: '#13a7e2',
          fontWeight: 'bold',
        },
        onClick: () => {
          viewImage(row.id || '')
        }
      }, row.diagramResourceName)
    }
  },
  {
    key: 'deploymentId',
    title: '部署id',
    align: 'center',
  },
  {
    key: 'deploymentTime',
    title: '部署时间',
    align: 'center',
    render(row: Flow.ProcessDefinition) {
      return h('span', {}, new Date(row.deploymentTime || 0).toLocaleString())
    }
  },
  {
    key: 'operate',
    title: $t('common.operate'),
    align: 'center',
    render: (row: Flow.ProcessDefinition) => (
      <div class="flex-center gap-8px">
        <NButton type="primary" ghost size="tiny" onClick={() => updateDefinitionState(row.id || '')}>
          {row.suspensionState === 1 ? '挂起' : '激活'}
        </NButton>
        <NButton type="primary" ghost size="tiny" onClick={() => openMigrationModal(row.id || '')}>
          迁移
        </NButton>
        <NPopconfirm onPositiveClick={() => handleDelete(row.deploymentId || '', row.id || '')}>
          {{
            default: () => $t('common.confirmDelete'),
            trigger: () => (
              <NButton type="error" ghost size="tiny">
                {$t('common.delete')}
              </NButton>
            )
          }}
        </NPopconfirm>
      </div>
    )
  }
]);

const deployModel = () => {
  emit('deploy-model', (error, data) => {
    getData();
    if (!error) {
      window.$message?.success('模型部署成功');
    }
  });
}

// 打开弹窗
const open = () => {
  showDrawer.value = true
}
// 关闭弹窗
const close = () => {
  showDrawer.value = false
}

// 删除
async function handleDelete(deploymentId: string, processDefinitionId: string) {
  startLoading();
  const {error, data} = await deleteDeployment(deploymentId, processDefinitionId);
  if (!error) {
    await getData();
    window.$message?.success('删除成功');
  } else {
    window.$message?.error(data || '删除失败');
  }
  endLoading();
}

// 激活或挂起
async function updateDefinitionState(processDefinitionId: string) {
  startLoading();
  const {error, data} = await fetchUpdateDefinitionState(processDefinitionId);
  if (!error) {
    await getData();
    window.$message?.success('操作成功');
  } else {
    window.$message?.error(data || '更新失败');
  }
  endLoading();
}

// 流程定义迁移
async function migrationDefinition() {
  startLoading();
  const {error, data} = await fetchMigrationDefinition(currentProcessDefinitionId.value, fromProcessDefinitionId.value);
  if (!error) {
    window.$message?.success('迁移成功');
    showMigrationModal.value = false
  } else {
    window.$message?.error(data || '迁移失败');
  }
  endLoading();
}

// 打开迁移弹窗
function openMigrationModal(id: string) {
  showMigrationModal.value = true
  currentProcessDefinitionId.value = id
}

// 获取迁移选项
function getFromProcessOption() {
  startLoading();
  if (data.value) {
    data.value.map((item: Flow.ProcessDefinition) => {
      if (item.id !== currentProcessDefinitionId.value) {
        fromProcessOptions.value.push({
          label: `${item.name}-v${item.version || '1'}`,
          value: item.id
        })
      }
    })
  }
  endLoading();
}

// 查看流程图片
async function viewImage(id: string) {
  let imageList: any = [];
  let {error, data} = await fetchGetDefinitionImage(id);
  if (!error) {
    imageList.push({
      url: "data:image/png;base64," + data
    });
    imgViewer.value.previewImage(0, imageList,{
      options: {
        className: 'whitebg',
        backdrop:false
      },
    });
  }
}

// 获取列表数据
async function getData() {
  startLoading();
  const res = await fetchGetDeployPage({
    pageNumber: 1,
    pageSize: 15,
    params: {
      key: props.template.flowData.model_code,
      name: props.template.flowData.model_name
    }
  });
  data.value = res.data?.content || [];
  endLoading();
}

defineExpose({
  open,
  close
});
watch(showDrawer, () => {
  if (showDrawer.value) {
    getData();
  } else {
    data.value = [];
  }
})
watch(showMigrationModal, () => {
  if (showMigrationModal.value === false) {
    currentProcessDefinitionId.value = '';
    fromProcessDefinitionId.value = '';
    fromProcessOptions.value = [];
    getData();
  } else {
    getFromProcessOption();
  }
})
</script>
<template>
  <div>
    <n-drawer v-model:show="showDrawer" :height="550" placement="bottom">
      <n-drawer-content>
        <template #header>
          模型部署列表
          <icon-material-symbols-lists style="font-size: 28px"/>
        </template>
        <n-data-table
          :bordered="true"
          :single-line="false"
          :columns="columns"
          :data="data"
          :size="'medium'"
          :flex-height="!appStore.isMobile"
          :scroll-x="640"
          :loading="loading"
          :pagination="pagination"
          :row-key="(item:Flow.ProcessDefinition) => item.id || ''"
          class="sm:h-full"
        />
        <template #footer>
          <n-button type="default" @click="getData" style="margin-right: 15px">
            <template #icon>
              <icon-material-symbols-refresh/>
            </template>
            刷新列表
          </n-button>
          <n-button type="primary" @click="deployModel">
            <template #icon>
              <icon-mdi-package-variant-closed-plus/>
            </template>
            部署当前模型
          </n-button>
        </template>
        <ImgViewer ref="imgViewer" image-url-key="url"/>
      </n-drawer-content>
    </n-drawer>
  </div>
  <n-modal
    v-model:show="showMigrationModal"
    :show-icon="false"
    preset="dialog"
    title="迁移流程定义"
    positive-text="确认"
    negative-text="取消"
    @positive-click="migrationDefinition"
    @negative-click="() => {
      showMigrationModal = false
    }"
  >
    <n-form label-placement="left" label-width="auto" style="width: 400px">
      <n-form-item label="当前流程">
        <n-input v-model:value="currentProcessDefinitionId" disabled/>
      </n-form-item>
      <n-form-item label="迁移至：">
        <n-select v-model:value="fromProcessDefinitionId" size="small" :options="fromProcessOptions"
                  placeholder="请选择"/>
      </n-form-item>
    </n-form>
  </n-modal>
</template>

<style scoped>

</style>
